package com.rzhd.coursepatriarch.common.utils.photo;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.rzhd.coursepatriarch.common.utils.file.FileSizeUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import cn.finalteam.rxgalleryfinal.RxGalleryFinal;
import cn.finalteam.rxgalleryfinal.RxGalleryFinalApi;
import cn.finalteam.rxgalleryfinal.bean.MediaBean;
import cn.finalteam.rxgalleryfinal.imageloader.ImageLoaderType;
import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultDisposable;
import cn.finalteam.rxgalleryfinal.rxbus.event.ImageMultipleResultEvent;
import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent;
import cn.finalteam.rxgalleryfinal.utils.MediaScanner;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import top.zibin.luban.CompressionPredicate;
import top.zibin.luban.Luban;
import top.zibin.luban.OnCompressListener;

/**
 * https://github.com/FinalTeam/RxGalleryFinal
 *
 * @author yql
 * Time: 2018/6/7.
 */
public class PhotoUtils {

    private final String TAG = getClass().getSimpleName();

    private static final int PICTURE_CODE = 10086;
    private static PhotoUtils mPhotoUtils;
    private Activity mContext;
    private Handler mHandler;
    private int maxChoice;

    private String picturePath;

    private Uri tempUri;
    public static final int MULTIPLE_SELECTION_PICTURE = 12;
    public static final int HANDLER_VIDEO_WHAT = 13;

    public PhotoUtils(Activity context) {
        this.mContext = context;
    }

    public static PhotoUtils getInstance(Activity context) {
        if (mPhotoUtils == null) {
            synchronized (PhotoUtils.class) {
                if (mPhotoUtils == null) {
                    mPhotoUtils = new PhotoUtils(context);
                }
            }
        }
        return mPhotoUtils;
    }

    /*-------------------------------------------图片选择-------------------------------------------*/

    /**
     * 拍摄照片
     */
    public void takePhoto(Handler handler) {
        this.mHandler = handler;
        //方案一
        RxGalleryFinalApi.openZKCamera(mContext);
        //方案二
//        this.picturePath = FileUtils.getBitmapDiskFile(mContext);
//        CameraUtils.openCamera(mContext, PICTURE_CODE, this.picturePath);
        //方案三
        //在启动拍照之前最好先判断一下sdcard是否可用
//        String state = Environment.getExternalStorageState(); //拿到sdcard是否可用的状态码
//        if (state.equals(Environment.MEDIA_MOUNTED)) {   //如果可用
//            Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
////            startActivityForResult( intent,TAKE_PHOTO_REQUEST_CODE );
//            tempUri = startActivityForResultElseMethod();
//        } else {
//            ToastUtils.shortToast("sdcard不可用");
//        }
    }

    /**
     * 选择照片
     *
     * @param handler   handler
     * @param maxChoice 最大选择图片数
     */
    public void choicePhoto(Handler handler, int maxChoice) {
        this.mHandler = handler;
        this.maxChoice = maxChoice;
//        if (maxChoice == 1) {
//            openImageSingle();
//        } else {
            openImageMultiple();
//        }
    }

    /**
     * 选择视频
     *
     * @param handler
     * @param maxChoice
     */
    public void choiceVideo(Handler handler, int maxChoice) {
        this.mHandler = handler;
        int count = (maxChoice <= 0 ? 1 : maxChoice);
        openVideoMultiple(count);
    }

    /**
     * 自定义单选
     */
    private void openImageSingle() {
        RxGalleryFinal
                .with(mContext)
                .image()
//                .radio()
//                .cropAspectRatioOptions(0, new AspectRatio("3:3", 30, 10))
//                .crop()
                .imageLoader(ImageLoaderType.GLIDE)
                .subscribe(new RxBusResultDisposable<ImageRadioResultEvent>() {
                    @Override
                    protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception {
                        Log.d(TAG, "单选后选择返回路径:" + imageRadioResultEvent.getResult().getOriginalPath());
                        compression(imageRadioResultEvent.getResult().getOriginalPath());
                    }
                })
                .openGallery();
    }

    /**
     * 自定义多选
     */
    private void openImageMultiple() {
        RxGalleryFinal
                .with(mContext)
                .image()
                .multiple()
                .maxSize(maxChoice)
                .imageLoader(ImageLoaderType.GLIDE)
                .subscribe(new RxBusResultDisposable<ImageMultipleResultEvent>() {
                    @Override
                    protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception {
//                        Toast.makeText(mContext, "已选择" + imageMultipleResultEvent.getResult().size() + "张图片", Toast.LENGTH_SHORT).show();
                        objectChange(imageMultipleResultEvent.getResult());
                    }

                    @Override
                    public void onComplete() {
                        super.onComplete();
//                        Toast.makeText(mContext, "OVER", Toast.LENGTH_SHORT).show();
                    }
                })
                .openGallery();
    }

    /**
     * 自定义多选视频
     */
    private void openVideoMultiple(int maxChoice) {
        RxGalleryFinal
                .with(mContext)
                .video()
                .multiple()
                .maxSize(maxChoice)
                .imageLoader(ImageLoaderType.GLIDE)
                .subscribe(new RxBusResultDisposable<ImageMultipleResultEvent>() {
                    @Override
                    protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception {
                        objectChangeToVideoFile(imageMultipleResultEvent.getResult());
                    }

                    @Override
                    public void onComplete() {
                        super.onComplete();
                    }
                })
                .openGallery();
    }


    /**
     * 防止系统内存不足销毁Activity
     * ,这里保存数据，便于恢复。
     *
     * @param outState
     */
    public void onSaveInstanceState(Bundle outState) {
        outState.putString(TAG, picturePath);
    }

    /**
     * 恢复被系统销毁的数据
     *
     * @param savedInstanceState
     */
    public void recoverState(Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            this.picturePath = savedInstanceState.getString(TAG);
        }
    }

    /**
     * 拍照返回处理
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    public void onActivityResult(int requestCode, int resultCode, Intent data, Handler handler) {
        this.mHandler = handler;
//        方案二
//        if (requestCode == PICTURE_CODE && resultCode == Activity.RESULT_OK) {
//            File file = new File(picturePath);
//            if (file.exists()) {
//                Log.e(TAG, "文件存在" + picturePath);
//                compression(picturePath);
//            } else {
//                Log.e(TAG, "文件不存在" + picturePath);
//            }
//        }
        //方案一
        if (requestCode == RxGalleryFinalApi.TAKE_IMAGE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            Log.i(TAG, "拍照OK，图片路径:" + RxGalleryFinalApi.fileImagePath.getPath());
            if (RxGalleryFinalApi.fileImagePath.getPath() != null && !TextUtils.isEmpty(RxGalleryFinalApi.fileImagePath.getPath())) {
                compression(RxGalleryFinalApi.fileImagePath.getPath());
            }
            //刷新相册数据库
            RxGalleryFinalApi.openZKCameraForResult(mContext, new MediaScanner.ScanCallback() {
                @Override
                public void onScanCompleted(String[] strings) {
                    Log.i(TAG, String.format("拍照成功,图片存储路径:%s", strings[0]));
                    Log.d(TAG, "演示拍照后进行图片裁剪，根据实际开发需求可去掉上面的判断");

//                    RxGalleryFinalApi.cropScannerForResult(mContext, RxGalleryFinalApi.getModelPath(), strings[0]);//调用裁剪.RxGalleryFinalApi.getModelPath()为默认的输出路径
                }
            });
        } else {
            Log.e(TAG, "失敗");
            sendErrorMessage("拍照返回失败");
        }
    }

    /*-------------------------------------------图片选择-------------------------------------------*/



    /*-------------------------------------------图片压缩-------------------------------------------*/


    /**
     * 单张照片压缩（异步调用）
     *
     * @param path
     */
    private void compression(String path) {
        Log.d(TAG, "鲁班压缩前大小-----" + FileSizeUtil.getAutoFileOrFilesSize(path));
        Luban.with(mContext)
                .load(path)
                .filter(new CompressionPredicate() {//设置开启压缩条件
                    @Override
                    public boolean apply(String path) {
                        return !TextUtils.isEmpty(path);
                    }
                })
                .ignoreBy(100)//不压缩的阈值，单位为K
//                .setTargetDir()//缓存压缩图片路径
                .setCompressListener(new OnCompressListener() {
                    @Override
                    public void onStart() {
                        // TODO 压缩开始前调用，可以在方法内启动 loading UI
                    }

                    @Override
                    public void onSuccess(File file) {
                        // TODO 压缩成功后调用，返回压缩后的图片文件
                        Log.d(TAG, "鲁班压缩后-----" + FileSizeUtil.getAutoFileOrFilesSize(file.getPath()));
                        sendMessage(file);
                    }

                    @Override
                    public void onError(Throwable e) {
                        // TODO 当压缩过程出现问题时调用
                        sendErrorMessage(e.getMessage());
                    }
                }).launch();
    }

    /**
     * 多张图片压缩
     *
     * @param pathList 图片路径列表
     */
    private void compression(List<String> pathList) {
        Flowable.just(pathList)
                .subscribeOn(Schedulers.io())
                .map(new Function<List<String>, List<File>>() {
                    @Override
                    public List<File> apply(List<String> pathList) throws Exception {
                        return Luban.with(mContext).load(pathList).get();
                    }
                }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<File>>() {
                    @Override
                    public void accept(List<File> files) throws Exception {
                        sendMessage(files);
                    }
                });
    }

    /*-------------------------------------------图片压缩-------------------------------------------*/


    /**
     * 多图
     * 测试使用rxjava
     * 实际上这个方法可以去除
     *
     * @param mediaBeans 图片地址对象
     */
    private void objectChange(List<MediaBean> mediaBeans) {
        Flowable.just(mediaBeans)
                .subscribeOn(Schedulers.newThread())
                .map(new Function<List<MediaBean>, List<String>>() {
                    @Override
                    public List<String> apply(List<MediaBean> mediaBeans) throws Exception {
                        List<String> strings = new ArrayList<>();
                        for (MediaBean bean : mediaBeans) {
                            strings.add(bean.getOriginalPath());
                        }
                        return strings;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<String>>() {
                    @Override
                    public void accept(List<String> strings) throws Exception {
                        compression(strings);
                    }
                });
    }

    /**
     * 转换成视频文件对象
     *
     * @param mediaBeans
     */
    private void objectChangeToVideoFile(List<MediaBean> mediaBeans) {
        Flowable.just(mediaBeans)
                .subscribeOn(Schedulers.newThread())
                .map(new Function<List<MediaBean>, List<String>>() {
                    @Override
                    public List<String> apply(List<MediaBean> mediaBeans) throws Exception {
                        List<String> strings = new ArrayList<>();
                        for (MediaBean bean : mediaBeans) {
                            strings.add(bean.getOriginalPath());
                        }
                        return strings;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<String>>() {
                    @Override
                    public void accept(List<String> strings) throws Exception {
                        filePathToFileObj(strings);
                    }
                });
    }

    /**
     * 文件路径集合转换成文件对象集合
     *
     * @param filePaths
     */
    private void filePathToFileObj(List<String> filePaths) {
        Flowable.just(filePaths)
                .subscribeOn(Schedulers.newThread())
                .map(new Function<List<String>, List<File>>() {
                    @Override
                    public List<File> apply(List<String> pathList) throws Exception {
                        List<File> results = new ArrayList<>();
                        for (String string : pathList) {
                            results.add(new File(string));
                        }
                        return results;
                    }
                }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<File>>() {
                    @Override
                    public void accept(List<File> files) throws Exception {
                        sendMessage(files, HANDLER_VIDEO_WHAT);
                    }
                });
    }

    private void sendErrorMessage(String error) {
        Message message = new Message();
        message.what = 10;
        message.obj = error;
        if (mHandler != null) {
            mHandler.sendMessage(message);
        }
    }

    /**
     * 单选
     * 发送选择图片路径到handler
     *
     * @param file 图片
     */
    private void sendMessage(File file) {
        //这里需要返回路径
        Message message = new Message();
        message.what = 11;
        message.obj = file;
        if (mHandler != null) {
            mHandler.sendMessage(message);
        }
    }

    /**
     * 多选
     * 发送选择图片路径到handler
     *
     * @param filePathList 图片路径
     */
    private void sendMessage(List<File> filePathList) {
        //这里需要返回路径
        Message message = new Message();
        message.what = MULTIPLE_SELECTION_PICTURE;
        message.obj = filePathList;
        if (mHandler != null) {
            mHandler.sendMessage(message);
        }
    }

    /**
     * 多选
     * 发送选择媒体路径到handler
     *
     * @param filePathList 图片路径
     */
    private void sendMessage(List<File> filePathList, int what) {
        //这里需要返回路径
        Message message = new Message();
        message.what = what;
        message.obj = filePathList;
        if (mHandler != null) {
            mHandler.sendMessage(message);
        }
    }

}
